package com.gitee.wsl.ext.reflect

import kotlin.reflect.KClassifier
import kotlin.reflect.KType
import kotlin.reflect.KTypeProjection


interface EitherNetKType {
    val classifier: KClassifier?
    val arguments: List<KTypeProjection>
    val isMarkedNullable: Boolean
    val annotations: List<Annotation>
}

internal class EitherNetKTypeImpl(
    override val classifier: KClassifier?,
    override val arguments: List<KTypeProjection>,
    override val isMarkedNullable: Boolean,
    override val annotations: List<Annotation>,
) : EitherNetKType {

    override fun toString(): String {
        return buildString {
            if (annotations.isNotEmpty()) {
                annotations.joinTo(this, " ") { "@$it" }
                append(' ')
            }
            append(classifier?.simpleToString() ?: "")
            if (arguments.isNotEmpty()) {
                append("<")
                arguments.joinTo(this, ", ") { it.toString() }
                append(">")
            }
            if (isMarkedNullable) {
                append("?")
            }
        }
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        // On the JVM we'd ideally do this too
        // if (javaClass != other?.javaClass) return false
        if (other !is KType) return false

        if (classifier != other.classifier) return false
        if (arguments != other.arguments) return false
        if (isMarkedNullable != other.isMarkedNullable) return false
        if (other is KTypeImpl) {
            if (annotations != other.annotations) return false
        }

        return true
    }

    override fun hashCode(): Int {
        var result = classifier?.hashCode() ?: 0
        result = 31 * result + arguments.hashCode()
        result = 31 * result + isMarkedNullable.hashCode()
        result = 31 * result + annotations.hashCode()
        return result
    }
}
